package com.tang.param_check.intecept;


import com.tang.param_check.aspect.annotation.ParamCheck;
import com.tang.param_check.aspect.handler.HandlerManager;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;

/**
 * 使用继承切面的方式
 * 其他的替代方案：MethodBeforeAdvice
 *
 * @Author tangyuan2meicloud.com
 * @DATE 2021/12/19 10:34
 * @Desc
 * @Remarks
 */
@Slf4j
@Component
public class ParamCheckMethodInterceptor implements MethodInterceptor {

    @Autowired
    private HandlerManager handlerManager;

    public Object invoke(MethodInvocation invocation) throws Throwable {
        log.info("参数切面校验开始！！");

        Method method = invocation.getMethod();
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        Object[] arguments = invocation.getArguments();
        for (int i = 0; i < parameterAnnotations.length; i++) {
            Annotation[] parameterAnnotation = parameterAnnotations[i];
            Object argument = arguments[i];
            for (Annotation annotation : parameterAnnotation) {
                Class<? extends Annotation> aClass = annotation.annotationType();
                /**
                 * 匹配到参数校验类
                 */
                if (aClass == ParamCheck.class) {
                    ParamCheck paramCheck = (ParamCheck) annotation;
                    Class handleClazz = paramCheck.handleClass();
                    if (argument instanceof Collection) {
                        checkCollectionParam(handleClazz, (Collection) argument);
                    } else {
                        checkSignalParam(handleClazz, argument);
                    }
                }
            }
        }
        log.info("参数切面校验结束！！");
        return invocation.proceed();
    }

    /**
     * 处理集合中定义了@ParamCheck的参数
     *
     * @param arg
     * @param clazz
     */
    private void checkCollectionParam(Class<?> clazz, Collection arg) {
        if (handlerManager.handleCollection(clazz, arg)) {
            log.info("集合参数校验处理成功");
        } else {

            throw new RuntimeException("参数校验处理失败！");
        }
    }

    /**
     * 处理直接类上定义了@ParamCheck的参数
     *
     * @param clazz
     * @param arg
     */
    private void checkSignalParam(Class<?> clazz, Object arg) {
        if (handlerManager.handle(clazz, arg)) {
            log.info("集合参数校验处理成功");
        } else {
            throw new RuntimeException("参数校验处理失败！");
        }

    }

}
